import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;

import javax.swing.*;

import java.util.ArrayList;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.beans.*;
import java.io.*;

/** 
    This class demonstrates the basics of setting up a Java Swing GUI uisng the
    BorderLayout. You should be able to use this program to drop in other
    components when building a GUI 
 */
public class MainWindow extends JFrame implements ActionListener{

	// Initialize all swing objects.


	
	//current category
	private JButton categoryButton = new JButton();

	private ArrayList<JButton> categories = new ArrayList<JButton>();
	private ArrayList<JButton> games = new ArrayList<JButton>();

	//needs to be after array are initalized because these use the arrays in their constructors
	private LevelsPane levelsPane = new LevelsPane();
	private final JPanel levelSelectPane = new JPanel();
	private final JPanel finalFrame = new JPanel(new GridLayout(3,1));
	private CardLayout finalFrameLayout = new CardLayout();
	private CategoriesPane categoriesPane = new CategoriesPane();
	
	// Menu
	private JMenuBar mb = new JMenuBar(); // Menubar
	private JMenu mnuFile = new JMenu("File"); // File Entry on Menu bar
	private JMenuItem mnuItemQuit = new JMenuItem("Quit"); // Quit sub item
	private JMenu mnuHelp = new JMenu("Help"); // Help Menu entry
	private JMenuItem mnuItemAbout = new JMenuItem("User Guide");// About Entry
	private JMenuItem mnuItemLookup = new JMenuItem("Look Up Word");//stuff for lookup table
	private JMenu mnuGotolevels = new JMenu("Goto Levels");

	int oldCategory = 0;
	String category = "Animals"; //category for the game to pull words from
	String level    = "1"; //level of difficulty of the words, 1 being the lowest
	String user = "";
	
	javax.swing.border.Border doneBorder = new javax.swing.border.LineBorder(Color.black, 4);

	public MainWindow()
	{

		setLocationByPlatform(true);
		this.setSize(700, 400);
		this.setResizable(false);
		this.setCursor(new Cursor(Cursor.HAND_CURSOR));
		//this.setIconImage(new ImageIcon("../imgs/world.jpeg").getImage());
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setTitle("Language Study");

		mnuItemQuit.addActionListener(new ListenMenuQuit());

		// Set menubar
		this.setJMenuBar(mb);

		//Build Menus
		mb.add(mnuFile);        // Add Menu items to form
		mb.add(mnuHelp);
		mb.add(mnuGotolevels);
		mnuHelp.add(mnuItemLookup);//create lookup line
		mnuFile.add(mnuItemQuit);  // Create Quit line
		mnuHelp.add(mnuItemAbout); // Create About line

		mnuGotolevels.addMenuListener(new javax.swing.event.MenuListener() {
			public void menuSelected(javax.swing.event.MenuEvent e)
			{
				fireGotolevels();
			}
			public void menuDeselected(javax.swing.event.MenuEvent e){}
			public void menuCanceled(javax.swing.event.MenuEvent e){}
		});
		
		mnuItemAbout.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
			    JFrame aboutUs = new JFrame();
				aboutUs.setMinimumSize(new Dimension(400,300));
				JTextArea display = new JTextArea(200,150);

				try {
				    String text = new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get("USER_GUIDE.txt")), java.nio.charset.StandardCharsets.UTF_8);				    
				    display.setText(text);
				}catch(Exception ex)
					{
					    ex.printStackTrace();
					}
				
				display.setEditable(false);
				aboutUs.add(new JScrollPane(display));
				aboutUs.setVisible(true);
			}
		});
		mnuItemLookup.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) 
			{
				JFrame lookup = new JFrame();
				JPanel panel = new JPanel();
				JLabel enterWord = new JLabel("Enter Word to Search");
				JTextField search = new JTextField(15);
				
				lookup.setSize(new Dimension(250,75));
				lookup.setLayout(new BoxLayout(lookup.getContentPane(), BoxLayout.X_AXIS));
				
				panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
				
				search.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
				enterWord.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
				lookup.add(panel);
				panel.add(enterWord);
				panel.add(search);
				search.addKeyListener(new KeyListener(){

					@Override
					public void keyPressed(KeyEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void keyReleased(KeyEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void keyTyped(KeyEvent arg0) {
						if(arg0.getKeyChar() == '\n'){
							JFrame answer = new JFrame();
							JLabel text = new JLabel("this is the mapping pair");
							answer.setSize(new Dimension(250,75));
							
							answer.setLayout(new BoxLayout(answer.getContentPane(), BoxLayout.X_AXIS));
							answer.add(text);
							answer.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
							answer.setVisible(true);
						}
						
					}
					
				});
				
				lookup.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
				lookup.setVisible(true);
			}
			
		});

	}

	public void start()
	{		
		for(int x = 1; x < Integer.parseInt( DB.getLevel(user) )+1; ++x)
		{
			addLevelButton(x);	
		}
		
		finalFrame.setLayout(finalFrameLayout);
		
		//final JPanel levelSelectLabelPane = new JPanel();
		levelSelectPane.setLayout(new GridLayout(3,1));
		
		JPanel levelselectlabelPane = new JPanel();
		JLabel levelSelectLabel = new JLabel("Select a level of diffculty:");
		levelSelectLabel.setFont(new Font("arial",Font.PLAIN,30));
		levelselectlabelPane.add(levelSelectLabel);
		
		levelSelectPane.add(levelselectlabelPane);
		levelSelectPane.add(levelsPane);
		
		//finalFrame.add(levelSelectLabelPane);
		//finalFrame.add(levelsPane);
		
		finalFrame.add(levelSelectPane, "levels");
		finalFrame.add(categoriesPane, "categories");
		this.add(finalFrame);
		finalFrameLayout.show(finalFrame, "levels");
		
		//can use card layout too
		levelsPane.addPropertyChangeListener(new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent evt) {
				if (evt.getPropertyName().equals("stop")) {

					setLevel(levelsPane.level);
					
					categoriesPane.construct();
					finalFrameLayout.show(finalFrame, "categories");
				}
			}

		});

	}
	
	private void addLevelButton(int x)
	{
		JButton b = new JButton("Level " + x);
		b.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				levelsPane.level = ((JButton)e.getSource()).getText().split("\\s+")[1];
				levelsPane.fade();
			}
		});
		levelsPane.add(b);	
	}

	private void getAndSetGames()
	{
		for(java.util.List<String> a : DB.getAllGames())
		{
			JButton b = new JButton(a.get(0));
			b.setEnabled(false);
			b.addActionListener(this);
			games.add(b);
		}
	}

	private void setLevel(String level)
	{
		this.level = level;
	}

	private void getAndSetCategories()
	{
		String [] doneCategories = DB.getDoneCategories(user,level);
		
		categories.clear();
		for(java.util.List<String> a : DB.getCategories(level))
		{
			String imgLocation = "";
			Image img = null;
			File imgFile = null;

			//imgs will be located in the root directory.
			if(a.get(1) == null) imgLocation = "imgs/" + a.get(0) + ".JPG";
			else 				   			 imgLocation = a.get(1);

			//its much much much much easier to just pass a file as an argument to ImageIO.read()
			imgFile = new File(imgLocation);

			try {
				img = ImageIO.read(imgFile);
			}catch (Exception e)
			{
				try{
					img = ImageIO.read(new File("imgs/wut.JPG"));
				}catch(Exception d){}//ummmmmmmmmmmmmmmmmm idk
			}


			JButton b = new JButton(new ImageIcon(img.getScaledInstance(100, 100, Image.SCALE_DEFAULT)));
			
			if(doneCategories != null)
				for(String c : doneCategories)
				{
					if(a.get(2).compareTo(c) == 0)
						b.setBorder(doneBorder);
				}
			else
				b.setBorder(doneBorder);
			
			b.setToolTipText("Study "+a.get(0));
			b.setBackground(new Color(100,200,100));
			b.setActionCommand("enable");
			b.addActionListener(this);
			categories.add(b);
		}
	}

	public class ListenMenuQuit implements ActionListener{
		public void actionPerformed(ActionEvent e){
			System.exit(0);  
		}
	}

	public void actionPerformed(ActionEvent e) 
	{
		if(!games.get(0).isEnabled())
		{
			for(JButton a : games)
				a.setEnabled(true);
		}


		//launch game
		for(JButton a : games)
		{
			if(e.getSource() == a)
			{
				try
				{

					for(JButton g : games)
						g.setEnabled(false);
					for(JButton c : categories)
						c.setEnabled(false);
					mnuGotolevels.setEnabled(false);

					Class<?> b = Class.forName(a.getText().replaceAll("\\s+",""));
					java.lang.reflect.Constructor<?> constructor = b.getConstructor(String.class,String.class);	
					final Game game = (Game)constructor.newInstance(new Object[]{category, level});

					game.addWindowListener(new WindowAdapter() {
						public void windowClosed(WindowEvent arg0) {
							System.out.println("score: "+game.getScore());//debug
							if(game.getScore() > 89)
							{
								//if it updates then set the border.
								if(DB.addDoneCategory(user,category,level))
									for(JButton c : categories)
										if(c.equals(categoryButton))
											c.setBorder(doneBorder);
								
								if(DB.isNewLevel(user, level))
									levelUp();
							}
							for(JButton g : games)
								g.setEnabled(true);
							for(JButton c : categories)
							    c.setEnabled(true);
							mnuGotolevels.setEnabled(true);
						}

					});
				}catch( Exception c )
				{
					c.printStackTrace();
					for(JButton ca : categories)
						ca.setEnabled(true);
				}
			}
		}

		//update icon to show which is selected and deselect old icon
		//this can also be in its own class if need be but shouldn't really matter
		for(JButton a : categories)
			if(e.getSource() == a)
			{
				categories.get(oldCategory).setBackground(new Color(100,200,100));
				a.setBackground(new Color(255,200,200));
				oldCategory = categories.indexOf(a);
				category = a.getToolTipText().split("\\s+")[1].toLowerCase();
				categoryButton = a;
			}
	}

	private void levelUp()
	{
		JOptionPane.showMessageDialog(this, "CONGRATULATIONS LEVEL UP!");
		addLevelButton(Integer.parseInt(level)+1);
		fireGotolevels();
	}
	
	private void fireGotolevels()
	{
		finalFrameLayout.show(finalFrame, "levels");
	}
	
	public void setUser ( String user )
	{
		this.user = user;
	}

	
	private class CategoriesPane extends JPanel
	{
		private JPanel pnlNorth = new JPanel(new GridLayout(2,1)); // North quadrant 
		private JPanel pnlSouth = new JPanel(); // South quadrant
		private JPanel pnlCenter = new JPanel(); // Center quadrant
		JLabel chooseLanLabel = new JLabel("Let's Learn Swahili!");
		
		public CategoriesPane()
		{
			this.setLayout(new GridLayout(3,1));
			chooseLanLabel.setFont(new Font("arial",Font.PLAIN,30));
			
			getAndSetGames();
			for(JButton a : games)
				pnlSouth.add(a);
		}
		
		public void construct()
		{
			pnlNorth.removeAll();
			pnlCenter.removeAll();
			
			//cause idk what i'm doing with layouts. gg.
			JPanel z = new JPanel();
			JPanel y = new JPanel();
			z.add(chooseLanLabel);
			y.add(new JLabel("level: "+level));
			pnlNorth.add(z);
			pnlNorth.add(y);
			
			getAndSetCategories();
			for(JButton a : categories)
				pnlCenter.add(a);
			
			
			this.removeAll();
			this.add(pnlNorth);
			this.add(pnlCenter);
			this.add(pnlSouth);
			this.revalidate();
		
		}
	}
	
	private class LevelsPane extends JPanel
	{
		public float alpha = 1.0f;
		public String level = "1";

		Timer fadeTimer;	
		JPanel pane = this;
		boolean isFading = false;
		BufferedImage buffer;

		public LevelsPane()
		{	
			fadeTimer = new Timer(100, new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					if (alpha < .05) 
					{
						fadeTimer.stop();
						isFading = false;
						buffer = null;
						firePropertyChange("stop",new String(""),new String("1"));
					} else 
					{
						isFading = true;
						alpha -= .1;
						pane.repaint();
					}
				}
			});	
		}
		
		public void fade()
		{
			buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
			fadeTimer.start();
		}

		public void paint(Graphics g) {
		    if (/*isFading*/ false) {// During fading, we prevent child components from being painted
				g.clearRect(0, 0, getWidth(), getHeight());
				((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
				g.drawImage(buffer, 0, 0, this);// We only draw an image of them with an alpha
			} else {
				super.paint(g);
			}
		}
	}
}




